package pl.edu.agh.soa.monitoring.client;

import java.util.Date;
import java.util.Random;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.jbi.JBIException;
import javax.jbi.messaging.DeliveryChannel;
import javax.jbi.messaging.ExchangeStatus;
import javax.jbi.messaging.InOnly;
import javax.jbi.messaging.MessageExchange;
import javax.jbi.messaging.MessagingException;
import javax.jbi.messaging.NormalizedMessage;
import javax.jbi.servicedesc.ServiceEndpoint;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;

import org.apache.log4j.Logger;
import org.apache.servicemix.MessageExchangeListener;
import org.apache.servicemix.bean.Destination;
import org.apache.servicemix.bean.ExchangeTarget;
import org.apache.servicemix.client.ClientFactory;
import org.apache.servicemix.client.ServiceMixClient;
import org.apache.servicemix.jbi.jaxp.SourceTransformer;
import org.apache.servicemix.jbi.jaxp.StringSource;
import org.apache.servicemix.jbi.util.MessageUtil;


public class ClientSenderBean implements MessageExchangeListener {

	private Logger logger = Logger.getLogger(this.getClass().getName());

	private ClientFactory factory;
	private ServiceMixClient client;
	private SenderThread sender;
	
	private static final int DEFAULT_RATE = 50;
	private static final int DEFAULT_SIZE = 10;
	
	Random random = new Random(new Date().getTime());
	
	@Resource
	private DeliveryChannel channel;

	@PostConstruct
	public void init() {
		if (channel == null) {
			throw new IllegalStateException("Bean not initialized, channel: " + channel);
		}
		logger.info(this.getClass().getName() + " initialized successfully.");
		try {
			factory = (ClientFactory) new InitialContext().lookup(ClientFactory.DEFAULT_JNDI_NAME);
			client = factory.createClient();
		} catch (NamingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JBIException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		sender = new SenderThread(client,DEFAULT_RATE,DEFAULT_SIZE);
		sender.start();
	}

	@PreDestroy
	public void destroy() {
		sender.kill();
	}

	public void onMessageExchange(MessageExchange exchange)
			throws MessagingException {
			if (exchange.getStatus() == ExchangeStatus.ACTIVE) {
	            NormalizedMessage msg = exchange.getMessage("in");
	            logger.info(msg);
	            msg.setContent(new StringSource("<ack>Message received<date>"+new Date()+"</date></ack>"));
	            exchange.setMessage(msg, "out");
	            channel.send(exchange);
	            Object rateObject = exchange.getProperty("rate");
	            Object sizeObject = exchange.getProperty("size");
	            int rate = ClientSenderBean.DEFAULT_RATE;
	            int size = ClientSenderBean.DEFAULT_SIZE;
	            if (rateObject != null){
	            	rate = Integer.parseInt((String)rateObject);
	            }else{
	            	logger.info("Rate property not setted.");
	            }
	            if (sizeObject != null){
	            	size = Integer.parseInt((String)sizeObject);
	            }else{
	            	logger.info("Size property not setted.");
	            }
	            logger.info("Received message on exchange: " + exchange);
	            sender.changeRate(rate,size);
	    		sender.changeState();
	        }
	}
	
	private void sendDataPacket(){
		try {
			QName service = new QName("http://test.com", "monitoringService");
			ServiceEndpoint endpoint = client.getContext().getEndpoint(service, "senderEndpoint");
			
			for (int i = 0; i < DEFAULT_RATE; i++) {
//				MarketData md = new MarketData();
//				md.setPrice(Symbols.nextPrice(md.getPrice()));
//				md.setVolume(Symbols.nextVolume(10));
				InOnly exchange = client.createInOnlyExchange();
				NormalizedMessage message = exchange.createMessage();
//				message.setProperty("data", md);
				// lets use a specific service to dispatch to
				exchange.setEndpoint(endpoint);
				client.send(exchange);
				logger.info(i);
			}
			logger.info(DEFAULT_RATE + " events sended.");
//			Thread.sleep(random.nextLong() % 1000);
		} catch (MessagingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
